package org.dromara.house.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.dromara.common.core.domain.R;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.house.domain.bo.LeasingTrendsBo;
import org.dromara.house.domain.dto.*;
import org.dromara.house.domain.entity.ParkFloor;
import org.dromara.house.domain.entity.ParkHousing;
import org.dromara.house.mapper.ParkFloorMapper;
import org.dromara.house.mapper.ParkHousingMapper;
import org.dromara.house.mapper.StatisticsMapper;
import org.dromara.house.service.StatisticsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class StatisticsServiceImpl implements StatisticsService {

    @Autowired
    private StatisticsMapper statisticsMapper;

    @Autowired
    private ParkHousingMapper parkHousingMapper;

    @Autowired
    private ParkFloorMapper parkFloorMapper;


    @Override
    public R<List<DistrictOccupancyRateDto>> districtOccupancyRate() {
        List<DistrictOccupancyRateDto> list = statisticsMapper.districtOccupancyRate();
        return R.ok(list);
    }

    @Override
    public R<List<HousingOccupancyRateDto>> housingOccupancyRate() {
        List<HousingOccupancyRateDto> list = statisticsMapper.housingOccupancyRate();
        return R.ok(list);
    }

    @Override
    public R<List<LeasingTrendsDto>> leasingTrends(LeasingTrendsBo bo) {
        Double totalArea = 0D;
        if (ObjectUtil.isEmpty(bo.getFloor())) {
            //楼层为空，获取片区或者楼层总面积
            totalArea = statisticsMapper.queryTotalArea(bo);
        } else {
            //楼层不为空，获取楼层总面积
            ParkFloor parkFloor = parkFloorMapper.selectById(bo.getFloor());
            if (ObjectUtil.isEmpty(parkFloor)) {
                return R.fail("楼层不存在！");
            }
            totalArea = parkFloor.getFloorArea();
        }
        List<LeasingTrendsDto> list = new ArrayList<>();
        for (String month : getCurrentAndLastFiveMonths()) {
            LeasingTrendsDto dto = statisticsMapper.queryLeasingTrendsDto(bo, month);
            dto.setMonth(month);
            dto.setTotalArea(totalArea);
            list.add(dto);
        }
        return R.ok(list);
    }

    @Override
    public R<OverallStatisticsDto> overallStatistics() {
        Date date = new Date();
        OverallStatisticsDto dto = new OverallStatisticsDto();
        LambdaQueryWrapper<ParkHousing> housingWrapper = new LambdaQueryWrapper<>();
        housingWrapper.eq(ParkHousing::getDeleteStatus, 0);
        //总楼宇数量
        List<ParkHousing> parkHousings = parkHousingMapper.selectList(housingWrapper);
        //总面积
        Double totalArea = statisticsMapper.queryTotalArea(null);
        //入驻企业数量
        Integer totalEnterprise = statisticsMapper.selectListParkTenantNum(null);
        //已租赁面积
        Double leaseArea = statisticsMapper.queryLeaseArea(null);
        //未租赁面积
        Double notLeasedArea = totalArea - leaseArea;
        //即将到期面积
        Date date1 = get60DaysLater(date);
        Double expiringSoon = statisticsMapper.selectExpiringSoon(date, date1, null);
        //即将到期企业
        List<ExpiringSoonEnterpriseDto> tenants = statisticsMapper.selectExpiringSoonEnterprise(date, date1, null);
        dto.setTotalHousing(parkHousings.size());
        dto.setTotalArea(totalArea);
        dto.setTotalEnterprise(totalEnterprise);
        //出租率
        // 用字符串构造 BigDecimal 避免精度丢失（关键！）
        BigDecimal num1 = new BigDecimal(leaseArea);
        BigDecimal num2 = new BigDecimal(totalArea);
        // 执行除法运算，保留 3 位小数，四舍五入
        BigDecimal result = num1.divide(
            num2,
            3,                // 保留小数位数
            RoundingMode.HALF_UP  // 四舍五入规则
        );
        // 转换为 double 类型
        double finalResult = result.doubleValue();
        dto.setOccupancyRate(finalResult);
        //已租赁面积
        dto.setRentedArea(leaseArea);
        dto.setNotRentedArea(notLeasedArea);
        //即将到期面积
        dto.setExpiringSoonArea(expiringSoon);
        //即将到期企业
        dto.setExpiringSoonEnterprise(tenants.size());
        dto.setExpiringSoonEnterpriseDtoList(tenants);
        return R.ok(dto);
    }

    @Override
    public R<DistrictStatisticsDto> districtStatistics(LeasingTrendsBo bo) {
        Date date = new Date();
        DistrictStatisticsDto dto = new DistrictStatisticsDto();
        LambdaQueryWrapper<ParkHousing> housingWrapper = new LambdaQueryWrapper<>();
        housingWrapper.eq(ParkHousing::getDeleteStatus, 0);
        housingWrapper.eq(ObjectUtil.isNotEmpty(bo.getDistrictId()), ParkHousing::getDistrictId, bo.getDistrictId());
        //总楼宇数量
        List<ParkHousing> parkHousings = parkHousingMapper.selectList(housingWrapper);
        //总面积
        Double totalArea = statisticsMapper.queryTotalArea(bo);
        //入驻企业数量
        Integer totalEnterprise = statisticsMapper.selectListParkTenantNum(bo);
        //已租赁面积
        Double leaseArea = statisticsMapper.queryLeaseArea(bo);
        //未租赁面积
        Double notLeasedArea = totalArea - leaseArea;
        //即将到期面积
        Date date1 = get60DaysLater(date);
        Double expiringSoon = statisticsMapper.selectExpiringSoon(date, date1, bo);
        //即将到期企业
        List<ExpiringSoonEnterpriseDto> tenants = statisticsMapper.selectExpiringSoonEnterprise(date, date1, bo);
        dto.setTotalHousing(parkHousings.size());
        dto.setTotalArea(totalArea);
        dto.setTotalEnterprise(totalEnterprise);
        //出租率
        // 用字符串构造 BigDecimal 避免精度丢失（关键！）
        BigDecimal num1 = new BigDecimal(leaseArea);
        BigDecimal num2 = new BigDecimal(totalArea);
        if (totalArea > 0) {
            // 执行除法运算，保留 3 位小数，四舍五入
            BigDecimal result = num1.divide(
                num2,
                3,                // 保留小数位数
                RoundingMode.HALF_UP  // 四舍五入规则
            );
            // 转换为 double 类型
            double finalResult = result.doubleValue();
            dto.setOccupancyRate(finalResult);
        } else {
            dto.setOccupancyRate(0D);
        }

        //已租赁面积
        dto.setRentedArea(leaseArea);
        dto.setNotRentedArea(notLeasedArea);
        //即将到期面积
        dto.setExpiringSoonArea(expiringSoon);
        //即将到期企业
        dto.setExpiringSoonEnterprise(tenants.size());
        return R.ok(dto);
    }

    @Override
    public R<HousingStatisticsDto> housingStatistics(LeasingTrendsBo bo) {
        HousingStatisticsDto dto = new HousingStatisticsDto();
        Date date = new Date();
        //总面积
        Double totalArea = statisticsMapper.queryTotalArea(bo);
        //入驻企业数量
        Integer totalEnterprise = statisticsMapper.selectListParkTenantNum(bo);
        //已租赁面积
        Double leaseArea = statisticsMapper.queryLeaseArea(bo);
        //未租赁面积
        Double notLeasedArea = totalArea - leaseArea;
        //即将到期面积
        Date date1 = get60DaysLater(date);
        Double expiringSoon = statisticsMapper.selectExpiringSoon(date, date1, bo);
        //即将到期企业
        List<ExpiringSoonEnterpriseDto> tenants = statisticsMapper.selectExpiringSoonEnterprise(date, date1, bo);
        dto.setTotalArea(totalArea);
        dto.setTotalEnterprise(totalEnterprise);
        //出租率
        // 用字符串构造 BigDecimal 避免精度丢失（关键！）
        BigDecimal num1 = new BigDecimal(leaseArea);
        BigDecimal num2 = new BigDecimal(totalArea);
        // 执行除法运算，保留 3 位小数，四舍五入
        if (totalArea > 0) {
            // 执行除法运算，保留 3 位小数，四舍五入
            BigDecimal result = num1.divide(
                num2,
                3,                // 保留小数位数
                RoundingMode.HALF_UP  // 四舍五入规则
            );
            // 转换为 double 类型
            double finalResult = result.doubleValue();
            dto.setOccupancyRate(finalResult);
        } else {
            dto.setOccupancyRate(0D);
        }
        //已租赁面积
        dto.setRentedArea(leaseArea);
        dto.setNotRentedArea(notLeasedArea);
        //即将到期面积
        dto.setExpiringSoonArea(expiringSoon);
        //即将到期企业
        dto.setExpiringSoonEnterprise(tenants.size());
        return R.ok(dto);
    }

    @Override
    public TableDataInfo<ParkHousingDto> selectPageList(LeasingTrendsBo bo, PageQuery pageQuery) {
        Page<ParkHousingDto> page = statisticsMapper.selectPageList(bo, pageQuery.build());
        Date date = new Date();
        for (ParkHousingDto record : page.getRecords()) {
            bo.setHousingId(record.getId());
            //查询已租赁面积
            //已租赁面积
            Double leaseArea = statisticsMapper.queryLeaseArea(bo);
            //查询入驻企业数
            //入驻企业数量
            Integer totalEnterprise = statisticsMapper.selectListParkTenantNum(bo);
            //查询即将到期面积
            Date date1 = get60DaysLater(date);
            Double expiringSoon = statisticsMapper.selectExpiringSoon(date, date1, bo);

            record.setRentedArea(leaseArea);
            Double notRentedArea = record.getTotalArea() - leaseArea;
            record.setNotRentedArea(notRentedArea);
            BigDecimal num1 = new BigDecimal(leaseArea);
            BigDecimal num2 = new BigDecimal(record.getTotalArea());
            if (ObjectUtil.isEmpty(num2)||num2.equals(new BigDecimal(0))) {
                record.setOccupancyRate(0D);
            }else {
                // 执行除法运算，保留 3 位小数，四舍五入
                BigDecimal result = num1.divide(
                    num2,
                    3,                // 保留小数位数
                    RoundingMode.HALF_UP  // 四舍五入规则
                );
                // 转换为 double 类型
                double finalResult = result.doubleValue();
                record.setOccupancyRate(finalResult);
            }

            record.setTotalEnterprise(totalEnterprise);
            record.setExpiringSoonArea(expiringSoon);

        }
        return TableDataInfo.build(page);
    }

    public Date get60DaysLater(Date date) {
        // 直接偏移 60 天（第一个参数为当前时间字符串，第二个为偏移天数）
        return DateUtil.offsetDay(date, 60);
    }

    /**
     * 获取本月及之前五个月的月份列表（正序：最早到最近，格式：yyyy-MM）
     * 示例：[2025-04, 2025-05, 2025-06, 2025-07, 2025-08, 2025-09]（假设当前是2025-09）
     */
    public static List<String> getCurrentAndLastFiveMonths() {
        List<String> monthList = new ArrayList<>();
        Date currentDate = DateUtil.date(); // 当前日期

        // 反向循环：i 从 5 到 0（共6次），先计算更早的月份
        for (int i = 5; i >= 0; i--) {
            // 向前偏移 i 个月（i=5 是前5个月，i=0 是当前月）
            Date offsetDate = DateUtil.offsetMonth(currentDate, -i);
            String month = DateUtil.format(offsetDate, "yyyy-MM");
            monthList.add(month); // 按顺序添加：前5个月 → 当前月
        }
        return monthList;
    }
}
